<script lang="ts">
	import type { FilterOption, MultiSelectFilterChangeEvent } from './types';

	// 响应式 props 声明
	let multiData = $state<FilterOption[]>([]);
	let title = $state<string>('');
	let showData = $state<string | string[] | null | undefined>(undefined);
	let onchange = $state<(e: MultiSelectFilterChangeEvent) => void>(() => {});

	// 监听外部 props 同步（仅同步，不触发额外逻辑）
	const props = $props();
	$effect(() => {
		multiData = props.multiData ?? [];
		title = props.title ?? '';
		showData = props.showData;
		onchange = props.onchange ?? (() => {});
	});

	// 内部响应式状态（仅存储基础选中状态，无联动逻辑）
	let statusType = $state<(FilterOption & { selected: boolean })[]>([]);
	let isCtrlActive = $state(false);
	let eventContainer = $state<HTMLDivElement | null>(null);
	let isClient = $state(false);
	let isInitialized = $state(false);
	let hasGroups = $state(false);

	// Ctrl 键监听（多选开关）
	const handleKeyDown = (e: KeyboardEvent) => {
		if (e.key.toLowerCase() === 'control') isCtrlActive = true;
	};

	const handleKeyUp = (e: KeyboardEvent) => {
		if (e.key.toLowerCase() === 'control') isCtrlActive = false;
	};

	// 环境判断 + 事件监听初始化（仅执行一次）
	$effect(() => {
		isClient = typeof window !== 'undefined';
		if (isClient) {
			window.addEventListener('keydown', handleKeyDown);
			window.removeEventListener('keyup', handleKeyUp);
			window.addEventListener('keyup', handleKeyUp);

			if (!isInitialized && multiData.length) {
				initData();
				isInitialized = true;
			}
		}

		return () => {
			if (isClient) {
				window.removeEventListener('keydown', handleKeyDown);
				window.removeEventListener('keyup', handleKeyUp);
			}
		};
	});

	/** 初始化筛选数据（仅执行一次） */
	const initData = () => {
		if (!isClient || !multiData.length || isInitialized) return;

		const copiedData = JSON.parse(JSON.stringify(multiData)) as FilterOption[];
		// 确保"全部"选项在最前面
		if (!copiedData.some((item) => item.name === '全部' && item.code === null)) {
			copiedData.unshift({ name: '全部', code: null, disabled: false });
		}

		// 初始化选中状态：仅"全部"选中，其他均未选中
		statusType = copiedData.map((item) => ({
			...item,
			selected: item.name === '全部' && item.code === null && !item.disabled,
			disabled: item.disabled || false
		}));

		// 检测是否存在组选项
		hasGroups = statusType.some((item) => item.sign === 'noData');

		// 处理回显逻辑
		if (showData !== undefined) {
			backShow(showData as string | string[] | null);
		}

		isInitialized = true;
	};

	/** 回显已选状态（仅更新基础状态，无联动） */
	const backShow = (value: string | string[] | null) => {
		if (!isInitialized || !statusType.length) return;

		// 清空所有选中状态
		statusType.forEach((item) => (item.selected = false));

		// 回显"全部"选中
		if (value === null) {
			const allOption = statusType.find((item) => item.name === '全部' && item.code === null);
			if (allOption && !allOption.disabled) {
				allOption.selected = true;
			}
			return;
		}

		// 处理字符串/数组类型回显
		const selectedCodes =
			typeof value === 'string'
				? value
						.split(',')
						.map((str) => str.trim())
						.filter(Boolean)
				: value.filter((id) => typeof id === 'string' && id.trim());

		// 仅回显子选项选中状态，组状态不主动更新（通过惰性计算显示）
		statusType.forEach((item) => {
			if (item.disabled || item.sign === 'noData' || item.code === null) return;
			item.selected = selectedCodes.includes(String(item.code));
		});
	};

	/** 惰性计算组是否应该选中（不修改响应式状态，仅返回结果） */
	const isGroupShouldSelected = (desc: string) => {
		if (!hasGroups || !statusType.length) return false;

		const children = statusType.filter(
			(item) =>
				item.description === desc && item.code !== null && !item.disabled && item.sign !== 'noData'
		);
		// 子选项全部选中时，组应该显示选中状态
		return children.length > 0 && children.every((child) => child.selected);
	};

	/** 获取"全部"选项（辅助函数） */
	const getAllOption = () => {
		return statusType.find((item) => item.name === '全部' && item.code === null);
	};

	/** 选项点击事件处理（完整 Ctrl 交互逻辑） */
	const handleClick = (item: (typeof statusType)[0], e: MouseEvent) => {
		e.stopPropagation();
		if (!isClient || !isInitialized || item.disabled) return;

		// 1. 按住 Ctrl 点击非"全部"标签 → 取消"全部"选中
		if (isCtrlActive && item.name !== '全部') {
			const allOption = getAllOption();
			if (allOption && allOption.selected) {
				allOption.selected = false;
			}
		}

		// 2. 按住 Ctrl 点击"全部"标签 → 清空其他仅保留自身选中
		if (isCtrlActive && item.name === '全部' && item.code === null) {
			statusType.forEach((opt) => (opt.selected = false));
			item.selected = true;
			emitEvents();
			return;
		}

		// 3. Ctrl+点击子选项 → 多选切换
		if (isCtrlActive && item.code !== null && item.sign !== 'noData' && item.name !== '全部') {
			item.selected = !item.selected;
			emitEvents();
			return;
		}

		// 4. 单独点击：先清空所有选中状态
		statusType.forEach((opt) => (opt.selected = false));

		// 4.1 点击"全部"选项（非 Ctrl 模式）
		if (item.name === '全部' && item.code === null) {
			item.selected = true;
			emitEvents();
			return;
		}

		// 4.2 点击组标签（仅更新组自身状态）
		if (item.sign === 'noData' && item.description) {
			item.selected = true;
			emitEvents();
			return;
		}

		// 4.3 点击子选项（仅更新自身状态）
		if (item.code !== null && item.sign !== 'noData') {
			item.selected = true;
			emitEvents();
			return;
		}
	};

	/** 派发事件（根据当前状态推导选中值） */
	const emitEvents = () => {
		if (!isClient || !eventContainer || !onchange) return;

		let selectedCodes: string[] = [];

		// 情况1："全部"选中
		const allSelected = statusType.some(
			(item) => item.name === '全部' && item.code === null && item.selected
		);
		if (allSelected) {
			selectedCodes = [];
		}
		// 情况2：有组选中（返回该组下所有子选项）
		else if (hasGroups) {
			const selectedGroup = statusType.find((item) => item.sign === 'noData' && item.selected);
			if (selectedGroup && selectedGroup.description) {
				selectedCodes = statusType
					.filter(
						(item) =>
							item.description === selectedGroup.description &&
							item.code !== null &&
							!item.disabled &&
							item.sign !== 'noData'
					)
					.map((item) => String(item.code));
			}
			// 情况3：无子组选中，返回选中的子选项
			else {
				selectedCodes = statusType
					.filter(
						(item) =>
							item.selected && item.code !== null && !item.disabled && item.sign !== 'noData'
					)
					.map((item) => String(item.code));
			}
		}
		// 情况4：无组，返回选中的子选项
		else {
			selectedCodes = statusType
				.filter(
					(item) => item.selected && item.code !== null && !item.disabled && item.sign !== 'noData'
				)
				.map((item) => String(item.code));
		}

		const event = new CustomEvent<MultiSelectFilterChangeEvent['detail']>('change', {
			detail: selectedCodes.length > 0 ? selectedCodes : null,
			bubbles: true,
			cancelable: true
		});

		eventContainer.dispatchEvent(event);
		onchange(event as MultiSelectFilterChangeEvent);
	};

	// 监听 showData 变化（仅回显基础状态）
	$effect(() => {
		if (isInitialized && showData !== undefined) {
			backShow(showData as string | string[] | null);
		}
	});
</script>

<div
	class="multiSelectFilter"
	bind:this={eventContainer}
	aria-label={title ? `${title}筛选器` : '多选筛选器'}
>
	{#if isInitialized && statusType.length}
		<div
			class="multiSelectFilter__options {title === '债券类型'
				? 'multiSelectFilter__options--bondType'
				: ''}"
		>
			{#each statusType as item, index (index + '-' + (item.code ?? item.name))}
				<button
					type="button"
					class="multiSelectFilter__tag
                        {item.selected ||
					(item.sign === 'noData' && item.description
						? isGroupShouldSelected(item.description)
						: false)
						? 'multiSelectFilter__tag--active'
						: ''}
                        {item.sign === 'noData' ? 'multiSelectFilter__tag--group' : ''}
                        {item.disabled ? 'multiSelectFilter__tag--disabled' : ''}"
					onclick={(e) => handleClick(item, e)}
					disabled={item.disabled}
					aria-pressed={item.selected ||
						(item.sign === 'noData' && item.description
							? isGroupShouldSelected(item.description)
							: false)}
					tabindex={item.disabled ? -1 : 0}
				>
					{item.name}
				</button>
			{/each}
		</div>
	{/if}
</div>

<style lang="scss">
	.multiSelectFilter {
		display: inline-block;
		box-sizing: border-box;

		&__options {
			&--bondType {
				width: 350px;
				.multiSelectFilter__tag:nth-child(3) {
					margin-right: 125px;
				}
				.multiSelectFilter__tag:nth-child(7) {
					margin-right: 70px;
				}
			}
		}
		&__tag {
			margin-right: 10px;
			margin-bottom: 8px;
			padding: 0 10px;
			height: 28px;
			cursor: pointer;
			border: 1px solid transparent;
			color: var(--color-info-700);
			user-select: none;
			font-size: 13px;

			&--active {
				border-color: var(--color-primary-500);
				color: var(--color-primary-500);
			}
			&--disabled {
				cursor: not-allowed;
				opacity: 0.7;
			}

			// Modifier 样式：组选项
			// &--group {}
		}
	}
</style>
